package org.notabug.lifeuser.moviedb;

import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.graphics.PorterDuff;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AlertDialog;
import android.support.v7.view.ContextThemeWrapper;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.MotionEvent;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.RatingBar;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.DatePicker;
import android.widget.NumberPicker;
import android.text.TextUtils;

import com.squareup.picasso.Picasso;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.text.SimpleDateFormat;
import java.text.ParseException;

import java.lang.Runnable;

import static org.notabug.lifeuser.moviedb.R.id.watchButton;
import static org.notabug.lifeuser.moviedb.R.id.watchedButton;

/*
* This class provides all the details about the movies (and series).
* This class makes it possible to add the movie/series to a list.
* Furthermore, it shows a list of the actors and similar movies.
*/
public class DetailActivity extends BaseActivity {

	private RecyclerView castView;
	private CastBaseAdapter castAdapter;
	private ArrayList<JSONObject> castArrayList;

	private RecyclerView similarMovieView;
	private SimilarMovieBaseAdapter similarMovieAdapter;
	private ArrayList<JSONObject> similarMovieArrayList;

	private Drawable mToolbarBackgroundDrawable;
	private Toolbar toolbar;

	private SQLiteDatabase database;
	private MovieDatabaseHelper databaseHelper;
	private int movieId;
	private String movieImageId;
	private String moviePosterId;
	private String voteAverage;
	private String movieName;

	private float amountStars;
	private boolean isMovie = true;

	private ImageView movieImage;
	private TextView movieTitle;
	private ImageView moviePoster;
	private TextView movieGenres;
	private TextView movieStartDate;
	private TextView movieFinishDate;
	private TextView movieRewatched;
	private RatingBar movieRating;
	private TextView movieDescription;

	private JSONObject jMovieObject;
	private String genres;

	private String startDate;
	private String finishDate;

	private int defaultButton;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_detail);	
		setNavigationDrawer();

		// Make the toolbar transparent.
		mToolbarBackgroundDrawable = new ColorDrawable(ContextCompat
				.getColor(getApplicationContext(), R.color.colorPrimary));
		mToolbarBackgroundDrawable.setAlpha(0);
		
		toolbar = (Toolbar) findViewById(R.id.toolbar);
		toolbar.setBackgroundDrawable(mToolbarBackgroundDrawable);

		// Make the transparency dependent on how far the user scrolled down.
		NotifyingScrollView notifyingScrollView = (NotifyingScrollView) 
				findViewById(R.id.scrollView);
		notifyingScrollView.setOnScrollChangedListener(mOnScrollChangedListener);

		if(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN_MR1) {
			mToolbarBackgroundDrawable.setCallback(drawableCallback);
		}

		// Set the layout of the two RecyclerViews.
		LinearLayoutManager castLinearLayoutManager = new LinearLayoutManager(this, 
				LinearLayoutManager.HORIZONTAL, false);

		LinearLayoutManager movieLinearLayoutManager = new LinearLayoutManager(this,
				LinearLayoutManager.HORIZONTAL, false);

		castView = (RecyclerView) findViewById(R.id.castRecyclerView);
		castView.setHasFixedSize(true); // Improves performance (if size is static)
		castView.setLayoutManager(castLinearLayoutManager);

		similarMovieView = (RecyclerView) findViewById(R.id.movieRecyclerView);
		similarMovieView.setHasFixedSize(true); // Improves performance (if size is static)
		similarMovieView.setLayoutManager(movieLinearLayoutManager);

		// Get the views from the layout.
		movieImage = (ImageView) findViewById(R.id.movieImage);
		movieTitle = (TextView) findViewById(R.id.movieTitle);
		moviePoster = (ImageView) findViewById(R.id.moviePoster);
		movieGenres = (TextView) findViewById(R.id.movieGenres);
		movieStartDate = (TextView) findViewById(R.id.movieStartDate);
		movieFinishDate = (TextView) findViewById(R.id.movieFinishDate);
		movieRewatched = (TextView) findViewById(R.id.movieRewatched);
		movieRating = (RatingBar) findViewById(R.id.movieRating);
		movieDescription = (TextView) findViewById(R.id.movieDescription);

		// Get the intent, get the JSONObject string and convert it back.
		// Send the JSONObject to the setMovieData method so all the data
		// will be displayed on the screen
		Intent intent = getIntent();
		isMovie = intent.getBooleanExtra("isMovie", true);
		try {
			setMovieData(new JSONObject(intent.getStringExtra("movieObject")));
			jMovieObject = new JSONObject(intent.getStringExtra("movieObject"));

			castArrayList = new ArrayList<JSONObject>();	
			castAdapter = new CastBaseAdapter(castArrayList, getApplicationContext());
			castView.setAdapter(castAdapter);

			similarMovieArrayList = new ArrayList<JSONObject>();
			similarMovieAdapter = new SimilarMovieBaseAdapter(similarMovieArrayList,
					getApplicationContext());
			similarMovieView.setAdapter(similarMovieAdapter);
		} catch(JSONException e) {
			e.printStackTrace();
		}

		// Get the cast for the CastListAdapter and get the movies for the MovieListAdapter.
		new CastList().execute();
		new SimilarMovieList().execute();

		// Load movie details.
		new MovieDetails().execute();

		// Check if the movie already exists in the database.
        databaseHelper = new MovieDatabaseHelper(getApplicationContext());
        database = databaseHelper.getWritableDatabase();

        databaseHelper.onCreate(database);
        Cursor cursor = database.rawQuery("SELECT * FROM " + MovieDatabaseHelper
				.TABLE_MOVIES + " WHERE " + MovieDatabaseHelper.COLUMN_MOVIES_ID + 
				"='" + movieId + "' LIMIT 1", null);
        if(cursor.getCount() <= 0) {
            // No record has been found, movie hasn't been added to the database.
            cursor.close();
        } else {
            cursor.moveToFirst();
            if(cursor.getInt(cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_WATCHED)) == 1) {
                // Change the buttons accordingly
                Button watchedButton = (Button) findViewById(R.id.watchedButton);
				watchedButton.getBackground().setColorFilter(
						getResources().getColor(R.color.colorGreen),
						PorterDuff.Mode.SRC_ATOP);
				watchedButton.setCompoundDrawablesWithIntrinsicBounds(
						getResources().getDrawable(R.drawable.ic_check),
						null, null, null);
				watchedButton.setTextColor(Color.WHITE);
            } else {
                // Change the buttons accordingly
                Button watchButton = (Button) findViewById(R.id.watchButton);
				watchButton.getBackground().setColorFilter(
						getResources().getColor(R.color.colorGreen),
						PorterDuff.Mode.SRC_ATOP);
				watchButton.setCompoundDrawablesWithIntrinsicBounds(
						getResources().getDrawable(R.drawable.ic_check),
						null, null, null);
				watchButton.setTextColor(Color.WHITE);
			}
        }
		// Pretty self-descriptive, needs to be run because onClick doesn't work.
		listenForRatingBarChanges();
	}

	private void setMovieData(JSONObject movieObject) {
		// Check if movieObject values differ from the current values,
		// if they do, use the movieObject values.
		try {
			// Set the movieId
			movieId = Integer.parseInt(movieObject.getString("id"));

			// Due to the difficulty of comparing images (or rather,
			// this can be a really slow process) the id of the image is
			// saved as class variable for easy comparison.
			if(movieObject.has("backdrop_path") && 
					!movieObject.getString("backdrop_path").equals(movieImageId)) {
				Picasso.with(this).load("https://image.tmdb.org/t/p/w780" + 
						movieObject.getString("backdrop_path"))
						.into(movieImage);

				Animation animation = AnimationUtils.loadAnimation(
						getApplicationContext(), R.anim.fade_in);
				movieImage.startAnimation(animation);

				// Set the old imageId to the new one.
				movieImageId = movieObject.getString("backdrop_path");
			}

			// Same goes for the movie poster of course.
			if(movieObject.has("poster_path") && 
					!movieObject.getString("poster_path").equals(moviePosterId)) {
				Picasso.with(this).load("https://image.tmdb.org/t/p/w154" + 
						movieObject.getString("poster_path"))
						.into(moviePoster);

				// Set the old posterId to the new one.
				moviePosterId = movieObject.getString("poster_path");
			}

			// Check if it is a movie or a series
			String title = (movieObject.has("title")) ? "title" : "name";

			if(movieObject.has(title) && 
					!movieObject.getString(title).equals(movieTitle
					.getText().toString())) {
				movieTitle.setText(movieObject.getString(title));
			}

			// The rating also uses a class variable for the same reason
			// as the image.
			databaseHelper = new MovieDatabaseHelper(getApplicationContext());
			database = databaseHelper.getWritableDatabase();

			databaseHelper.onCreate(database);

			Cursor cursor = database.rawQuery("SELECT * FROM " + 
					MovieDatabaseHelper.TABLE_MOVIES + 
					" WHERE " + MovieDatabaseHelper.COLUMN_MOVIES_ID + 
					"=" + movieId + " AND " + MovieDatabaseHelper.COLUMN_WATCHED +
					"=1 LIMIT 1", null);
			if(cursor.getCount() > 0) {
				cursor.moveToFirst();
				// Set the rating to the personal rating of the user.
				movieRating.setRating( cursor.getFloat(cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_PERSONAL_RATING)) / 2);

				// To make use of this opportunity (to prevent extra if-statements):

				// If the database has a start date, use it, otherwise print unknown.
				if(cursor.getString(cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_PERSONAL_START_DATE)) != null) {
					movieStartDate.setText(getString(R.string.start_date) + cursor.getString(
							cursor.getColumnIndex(MovieDatabaseHelper
							.COLUMN_PERSONAL_START_DATE)));
				} else {
					movieStartDate.setText(getString(R.string.start_date_unknown));
				}

				// If the database has a finish date, use it, otherwise print unknown.
				if(cursor.getString(cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_PERSONAL_FINISH_DATE)) != null) {
					movieFinishDate.setText(getString(R.string.finish_date) + cursor.getString(
							cursor.getColumnIndex(MovieDatabaseHelper
							.COLUMN_PERSONAL_FINISH_DATE)));
				} else {
					movieFinishDate.setText(getString(R.string.finish_date_unknown));
				}

				// If the database has an rewatched count, use it, otherwise it is 0.
				if(cursor.getString(cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_PERSONAL_REWATCHED)) != null) {
					movieRewatched.setText(getString(R.string.times_rewatched)+ cursor.getString(
							cursor.getColumnIndex(MovieDatabaseHelper
							.COLUMN_PERSONAL_REWATCHED)));
				} else {
					movieRewatched.setText(getString(R.string.zero_times_rewatched));
				}

				// Make all the views visible (only for movies in the database).
				movieStartDate.setVisibility(View.VISIBLE);
				movieFinishDate.setVisibility(View.VISIBLE);
				movieRewatched.setVisibility(View.VISIBLE);
			} else if(movieObject.has("vote_average") && 
					!movieObject.getString("vote_average").equals(voteAverage)) {
				// Set the avarage (non-personal) rating (if it isn't the same).
				movieRating.setRating(Float.parseFloat(movieObject
						.getString("vote_average")) / 2);
			}

			// If the overview (summary) is different in the new dataset, change it.
			if(movieObject.has("overview") && 
					!movieObject.getString("overview").equals(movieDescription
					.getText().toString()) && !movieObject.getString("overview")
					.equals("") && !movieObject.getString("overview").equals("null")) {
				movieDescription.setText(movieObject.getString("overview"));
				if(movieObject.getString("overview").equals("")) {
					new MovieDetails().execute("true");
				}
			}

			// Set the genres
			if(movieObject.has("genre_ids")) {
				// This works a bit different, 
				// the ids will be converted to genres first after that
				// the new text with genres will be compared to the old one.

				// Remove the [ and ] from the String
				String genreIds = movieObject.getString("genre_ids")
						.substring(1, movieObject.getString("genre_ids")
						.length() - 1);

				// Split the String with the ids and set them into an array.
				String[] genreArray = genreIds.split(",");

				// Get the sharedPreferences
				SharedPreferences sharedPreferences = getApplicationContext()
						.getSharedPreferences("GenreList", Context.MODE_PRIVATE);

				// Add all the genres in one String.
				String genreNames = "";
				for(int i = 0; i < genreArray.length; i++) {
					genreNames += ", " + sharedPreferences
							.getString(genreArray[i], genreArray[i]);
				}

				// Remove the first ", " from the String and set the text.
				movieGenres.setText(genreNames.substring(2));
				genres = genreNames.substring(2);
			}
		} catch(JSONException e) {
			e.printStackTrace();
		}
	}

	public void addMovieToWatchedList(View view) {
		// Create a database connection.
		databaseHelper = new MovieDatabaseHelper(getApplicationContext());
		database = databaseHelper.getWritableDatabase();

		databaseHelper.onCreate(database);

		// Check if the movie is already in the database.
		Cursor cursor = database.rawQuery("SELECT * FROM " + 
				MovieDatabaseHelper.TABLE_MOVIES + 
				" WHERE " + MovieDatabaseHelper.COLUMN_MOVIES_ID + 
				"=" + movieId + " LIMIT 1", null);
		
		if(cursor.getCount() <= 0) {
			// Ask the rating of the movie.
			final AlertDialog.Builder ratingDialog = new AlertDialog.Builder(this);
			ratingDialog.setTitle("Movie Rating:");
			LayoutInflater inflater = getLayoutInflater();
			final View dialogView = inflater.inflate(R.layout.ratingbar, null);
			ratingDialog.setView(dialogView);

			ratingDialog.setPositiveButton(getString(R.string.movie_rating_ok), new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialogInterface, int i) {
					RatingBar ratingBar = (RatingBar) dialogView.findViewById(R.id.movieRating);
					amountStars = ratingBar.getRating();
					dialogInterface.dismiss();

					if(amountStars <= 0) {
						// The user didn't give the movie a rating, 
						// dismiss the dialog and tell the user that
						// the movie is not added to the database.
						
						Toast.makeText(getApplicationContext(), getString(R.string.movie_not_added_to_list),
								Toast.LENGTH_SHORT).show();
						return;
					} else {
						ContentValues movieValues = new ContentValues();

						movieValues.put(MovieDatabaseHelper.COLUMN_WATCHED, 1);
						movieValues.put(MovieDatabaseHelper.COLUMN_PERSONAL_RATING,
								amountStars * 2);
						addMovieToDatabase(movieValues);
					}
				}
			});

			ratingDialog.setNegativeButton(getString(R.string.movie_rating_cancel), new DialogInterface.OnClickListener() {
				@Override
				public void onClick(DialogInterface dialogInterface, int i) {
					// User pressed cancel, dismiss the dialog
					dialogInterface.dismiss();
					return;
				}
			});

			ratingDialog.show();
		} else {
			ContentValues movieValues = new ContentValues();
			movieValues.put(MovieDatabaseHelper.COLUMN_WATCHED, 1);
			addMovieToDatabase(movieValues);
		}
	}

	public void addMovieToToWatchList(View view) {
		// Create a database connection and create ContentValues with 'watched' false.
		databaseHelper = new MovieDatabaseHelper(getApplicationContext());
		database = databaseHelper.getWritableDatabase();

		databaseHelper.onCreate(database);
		ContentValues movieValues = new ContentValues();

		movieValues.put(MovieDatabaseHelper.COLUMN_WATCHED, 0);
		addMovieToDatabase(movieValues);
	}

	private void addMovieToDatabase(ContentValues movieValues) {

		// Check if the movie is already in the database.
		Cursor cursor = database.rawQuery("SELECT * FROM " + 
				MovieDatabaseHelper.TABLE_MOVIES + 
				" WHERE " + MovieDatabaseHelper.COLUMN_MOVIES_ID + 
				"=" + movieId + " LIMIT 1", null);

		int valuesWatchedValue = movieValues.getAsInteger(MovieDatabaseHelper.COLUMN_WATCHED);

		Button watchedButton = (Button) findViewById(R.id.watchedButton);
		Button watchButton = (Button) findViewById(R.id.watchButton);

		if(cursor.getCount() <= 0) {
			// No record has been found, the movie isn't in the database.
			// The movie should be added to the database.

			try {
				movieValues.put(MovieDatabaseHelper.COLUMN_MOVIES_ID, 
						Integer.parseInt(jMovieObject.getString("id")));
				movieValues.put(MovieDatabaseHelper.COLUMN_IMAGE, 
						jMovieObject.getString("backdrop_path"));
				movieValues.put(MovieDatabaseHelper.COLUMN_ICON, 
						jMovieObject.getString("poster_path"));
				String title = (isMovie) ? "title" : "name";
				movieValues.put(MovieDatabaseHelper.COLUMN_TITLE, jMovieObject.getString(title));
				movieValues.put(MovieDatabaseHelper.COLUMN_SUMMARY, jMovieObject.getString("overview"));
				movieValues.put(MovieDatabaseHelper.COLUMN_GENRES, genres);
				movieValues.put(MovieDatabaseHelper.COLUMN_GENRES_IDS,
						jMovieObject.getString("genre_ids"));
				movieValues.put(MovieDatabaseHelper.COLUMN_MOVIE, isMovie);
				movieValues.put(MovieDatabaseHelper.COLUMN_RATING, 
						jMovieObject.getString("vote_average"));

				database.insert(MovieDatabaseHelper.TABLE_MOVIES, null, movieValues);

				Toast.makeText(this, getString(R.string.movie_added_to_list),
						Toast.LENGTH_SHORT).show();
			} catch(JSONException e) {
				e.printStackTrace();
			}

			if(valuesWatchedValue == 1) {

				watchedButton.getBackground().setColorFilter(getResources().getColor(R.color.colorGreen), PorterDuff.Mode.SRC_ATOP);
				watchedButton.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.ic_check), null, null, null);
				watchedButton.setTextColor(Color.WHITE);
			} else {
				watchButton.getBackground().setColorFilter(getResources().getColor(R.color.colorGreen), PorterDuff.Mode.SRC_ATOP);
				watchButton.setCompoundDrawablesWithIntrinsicBounds(getResources().getDrawable(R.drawable.ic_check), null, null, null);
				watchButton.setTextColor(Color.WHITE);
			}
		} else {
			// The movie is already in the database; remove the movie or 
			// move the movie to the other list.
			cursor.moveToFirst();

			if(cursor.getInt(cursor.getColumnIndex(
					MovieDatabaseHelper.COLUMN_WATCHED)) == movieValues
					.getAsInteger(MovieDatabaseHelper.COLUMN_WATCHED)) {

				// Remove the movie 
				database.delete(MovieDatabaseHelper.TABLE_MOVIES, 
						MovieDatabaseHelper.COLUMN_MOVIES_ID + "=" + movieId, null);

				Toast.makeText(this, getString(R.string.movie_removed_from_list),
						Toast.LENGTH_SHORT).show();

				if(valuesWatchedValue == 1) {
					watchedButton.getBackground().clearColorFilter();
					watchedButton.setCompoundDrawablesWithIntrinsicBounds(null,
							null, null, null);
					watchedButton.setTextColor(Color.BLACK);
				} else {
					watchButton.getBackground().clearColorFilter();
					watchButton.setCompoundDrawablesWithIntrinsicBounds(null, 
							null, null, null);
					watchButton.setTextColor(Color.BLACK);
				}
			} else {
				// Change the watched value in the database
				database.update(MovieDatabaseHelper.TABLE_MOVIES, movieValues,
						MovieDatabaseHelper.COLUMN_MOVIES_ID + "=" + movieId, null);

				Toast.makeText(this, getString(R.string.movie_moved_other_list),
						Toast.LENGTH_SHORT).show();

				if(valuesWatchedValue == 1) {
					watchButton.getBackground().clearColorFilter();
					watchButton.setCompoundDrawablesWithIntrinsicBounds(null, 
							null, null, null);
					watchButton.setTextColor(Color.BLACK);

					watchedButton.getBackground().setColorFilter(getResources()
							.getColor(R.color.colorGreen), PorterDuff.Mode.SRC_ATOP);
					watchedButton.setCompoundDrawablesWithIntrinsicBounds(
							getResources().getDrawable(R.drawable.ic_check),
							null, null, null);
					watchedButton.setTextColor(Color.WHITE);
				} else {
					watchedButton.getBackground().clearColorFilter();
					watchedButton.setCompoundDrawablesWithIntrinsicBounds(null,
							null, null, null);
					watchedButton.setTextColor(Color.BLACK);

					watchButton.getBackground().setColorFilter(getResources()
							.getColor(R.color.colorGreen), PorterDuff.Mode.SRC_ATOP);
					watchButton.setCompoundDrawablesWithIntrinsicBounds(
							getResources().getDrawable(R.drawable.ic_check),
							null, null, null);
					watchButton.setTextColor(Color.WHITE);
				}
			}
		}

		// Close all connections.
		cursor.close();
		database.close();
		databaseHelper.close();
	}

	private void listenForRatingBarChanges() {
		// Listen to clicks on the RatingBar.
		movieRating.setOnTouchListener(new OnTouchListener() {
			@Override
			public boolean onTouch(View v, MotionEvent event) {
				if(event.getAction() == MotionEvent.ACTION_UP) {

					// Check if the call is from a watched movie
					databaseHelper = new MovieDatabaseHelper(getApplicationContext());
					database = databaseHelper.getWritableDatabase();

					databaseHelper.onCreate(database);
					Cursor cursor = database.rawQuery("SELECT * FROM " + 
							MovieDatabaseHelper.TABLE_MOVIES + 
							" WHERE " + MovieDatabaseHelper.COLUMN_MOVIES_ID + 
							"=" + movieId + " LIMIT 1", null);
					if(!(cursor.getCount() <= 0)) {
						
						// Ask the rating of the movie.
						final AlertDialog.Builder ratingDialog = 
								new AlertDialog.Builder(new ContextThemeWrapper(
										DetailActivity.this, R.style.AppTheme));
						ratingDialog.setTitle(getString(R.string.change_movie_rating));
						LayoutInflater inflater = getLayoutInflater();
						final View dialogView = inflater.inflate(
								R.layout.ratingbar, null);
						ratingDialog.setView(dialogView);

						ratingDialog.setPositiveButton(getString(
								R.string.change_movie_rating_ok),
								new DialogInterface.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialogInterface, int i) {
								RatingBar ratingBar = (RatingBar) 
										dialogView.findViewById(R.id.movieRating);
								amountStars = ratingBar.getRating();
								dialogInterface.dismiss();

								if(amountStars <= 0) {
									// The user didn't give the movie a rating,
									// dismiss the dialog 				
									return;
								} else {
									ContentValues movieValues = new ContentValues();

									movieValues.put(MovieDatabaseHelper
											.COLUMN_PERSONAL_RATING,
											amountStars * 2);
									database.update(MovieDatabaseHelper
											.TABLE_MOVIES, movieValues,
											MovieDatabaseHelper.COLUMN_MOVIES_ID + 
											"=" + movieId, null);

									// Update the view
									movieRating.setRating(amountStars);
								}
							}
						});

						ratingDialog.setNegativeButton(getString(
								R.string.change_movie_rating_cancel),
								new DialogInterface.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialogInterface,
									int i) {
								// User pressed cancel, dismiss the dialog
								dialogInterface.dismiss();
								return;
							}
						});

						ratingDialog.show();
					}
				}
				return true;
			}
		});
	}

	public void changeMovieDate(final View view) {
		// Ask the new date
		final AlertDialog.Builder dateDialog = 
				new AlertDialog.Builder(new ContextThemeWrapper(DetailActivity.this,
				R.style.AppTheme));

		LayoutInflater inflater = getLayoutInflater();
		final View dialogView = inflater.inflate(R.layout.date_change_dialog, null);
		dateDialog.setView(dialogView);

		// Set the date for the DatePicker & set the dialog title
        Cursor cursor = database.rawQuery("SELECT * FROM " +
				MovieDatabaseHelper.TABLE_MOVIES + " WHERE " +
				MovieDatabaseHelper.COLUMN_MOVIES_ID + "='" +
				movieId + "' LIMIT 1", null);
		cursor.moveToFirst();

		DatePicker datePicker = (DatePicker) dialogView
				.findViewById(R.id.movieDatePicker);
		SimpleDateFormat simpleDateFormat = new SimpleDateFormat("d MMMM yy");
		TextView movieDateChangerExplanation = (TextView) dialogView.findViewById(
				R.id.movieDateChangerExplanation);
		if(view.getId() == R.id.movieStartDate) {
			dateDialog.setTitle(getString(R.string.change_start_date));
			movieDateChangerExplanation.setText(getString(
					R.string.movie_start_date_change_explanation));
			// Set date from database if available.
			if(!TextUtils.isEmpty(cursor.getString(cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_PERSONAL_START_DATE)))) {
				try {
					// If the database already contains a date, parse it to SDF,
					// and set if via a Calendar to the DatePicker.
					Date date = simpleDateFormat.parse(cursor.getString(
							cursor.getColumnIndex(MovieDatabaseHelper
							.COLUMN_PERSONAL_START_DATE)));
					Calendar calendar = Calendar.getInstance();
					calendar.setTime(date);
					datePicker.init(calendar.get(Calendar.YEAR),
							calendar.get(Calendar.MONTH),
							calendar.get(Calendar.DAY_OF_MONTH), null);
				} catch(ParseException e) {
					e.printStackTrace();
				}
			}
		} else {
			dateDialog.setTitle(getString(R.string.change_finish_date));
			movieDateChangerExplanation.setText(getString(
					R.string.movie_finish_date_change_explanation));
			// Set date from database if available.
			if(!TextUtils.isEmpty(cursor.getString(cursor.getColumnIndex(
						MovieDatabaseHelper.COLUMN_PERSONAL_FINISH_DATE)))) {
				try {
					// If the database already contains a date, parse it to SDF,
					// and set if via a Calendar to the DatePicker.
					Date date = simpleDateFormat.parse(cursor.getString(
							cursor.getColumnIndex(MovieDatabaseHelper
							.COLUMN_PERSONAL_FINISH_DATE)));
					Calendar calendar = Calendar.getInstance();
					calendar.setTime(date);
					datePicker.init(calendar.get(Calendar.YEAR),
							calendar.get(Calendar.MONTH),
							calendar.get(Calendar.DAY_OF_MONTH), null);
				} catch(ParseException e) {
					e.printStackTrace();
				}
			}
		}

		dateDialog.setPositiveButton(getString(R.string.change_date_save),
				new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialogInterface, int i) {
				// Get the date from the DatePicker.
				DatePicker datePicker = (DatePicker) dialogView
						.findViewById(R.id.movieDatePicker);
				SimpleDateFormat dateformat = new SimpleDateFormat("d MMMM yy");
				String dateFormat = dateformat.format(new Date(datePicker.getYear(),
						datePicker.getMonth(), datePicker.getDayOfMonth()));

				// Save the date to the database and update the view
				ContentValues movieValues = new ContentValues();

				if(view.getId() == R.id.movieStartDate) {
					movieValues.put(MovieDatabaseHelper
							.COLUMN_PERSONAL_START_DATE, dateFormat);
					movieStartDate.setText(getString(R.string.change_start_date_2) +
							dateFormat);
				} else {
					movieValues.put(MovieDatabaseHelper
							.COLUMN_PERSONAL_FINISH_DATE, dateFormat);
					movieFinishDate.setText(getString(R.string.change_finish_date_2) 
							+ dateFormat);
				}
				database.update(MovieDatabaseHelper.TABLE_MOVIES, movieValues,
						MovieDatabaseHelper.COLUMN_MOVIES_ID + "=" + movieId, null);
				dialogInterface.dismiss();
			}
		});

		dateDialog.setNegativeButton(getString(R.string.change_date_cancel),
				new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialogInterface, int i) {
				// User pressed cancel, dismiss the dialog
				dialogInterface.dismiss();
				return;
			}
		});

		dateDialog.show();
	}

	public void changeRewatched(View view) {
		// Ask how many times the show has been rewatched
		final AlertDialog.Builder rewatchedDialog =
				new AlertDialog.Builder(new ContextThemeWrapper(DetailActivity.this, 
				R.style.AppTheme));

		rewatchedDialog.setTitle(getString(R.string.change_rewatched));

		LayoutInflater inflater = getLayoutInflater();
		final View dialogView = inflater.inflate(
				R.layout.rewatch_change_dialog, null);
		rewatchedDialog.setView(dialogView);

		NumberPicker numberPicker = (NumberPicker) dialogView
		.findViewById(R.id.movieRewatchedPicker);
		numberPicker.setMinValue(0);
		numberPicker.setMaxValue(9999); // Only set because it is mandatory.

		// Set the default value
        Cursor cursor = database.rawQuery("SELECT * FROM " + 
				MovieDatabaseHelper.TABLE_MOVIES + " WHERE " + 
				MovieDatabaseHelper.COLUMN_MOVIES_ID + "='" + movieId + 
				"' AND " + MovieDatabaseHelper.COLUMN_PERSONAL_REWATCHED + 
				" IS NOT NULL LIMIT 1", null);
		cursor.moveToFirst();
		if(cursor.getCount() > 0) {
			numberPicker.setValue(cursor.getInt(cursor.getColumnIndex(
					MovieDatabaseHelper.COLUMN_PERSONAL_REWATCHED)));
		} else {
			// If there isn't a value in the database, it's probably the first time.
			numberPicker.setValue(1);
		}

		rewatchedDialog.setPositiveButton(getString(R.string.change_rewatched_save),
				new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialogInterface, int i) {
				NumberPicker numberPicker = (NumberPicker) dialogView
				.findViewById(R.id.movieRewatchedPicker);

				// Save the number to the database
				ContentValues movieValues = new ContentValues();
				movieValues.put(MovieDatabaseHelper.COLUMN_PERSONAL_REWATCHED,
						numberPicker.getValue());
				database.update(MovieDatabaseHelper.TABLE_MOVIES, movieValues,
						MovieDatabaseHelper.COLUMN_MOVIES_ID + "=" + movieId, null);

				// Update the view
				movieRewatched.setText(getString(R.string.change_rewatched_times) + 
						Integer.toString(numberPicker.getValue()));
				
				dialogInterface.dismiss();
			}
		});

		rewatchedDialog.setNegativeButton(getString(R.string.change_rewatched_cancel),
				new DialogInterface.OnClickListener() {
			@Override
			public void onClick(DialogInterface dialogInterface, int i) {
				// User pressed cancel, dismiss the dialog
				dialogInterface.dismiss();
				return;
			}
		});

		rewatchedDialog.show();
	}

	private NotifyingScrollView.OnScrollChangedListener 
			mOnScrollChangedListener = new NotifyingScrollView
			.OnScrollChangedListener() {
		public void onScrollChanged(ScrollView scrollView,
				int l, int t, int oldl, int oldt) {
			final int headerHeight = findViewById(R.id.movieImage).getHeight() - 
					toolbar.getHeight();
			final float ratio = (float) Math.min(Math.max(t, 0),
					headerHeight) / headerHeight;
			final int newAlpha = (int) (ratio * 255);
			mToolbarBackgroundDrawable.setAlpha(newAlpha);
		}
	};

	private Drawable.Callback drawableCallback = new Drawable.Callback() {
		@Override
		public void invalidateDrawable(Drawable drawable) {
			toolbar.setBackgroundDrawable(drawable);
		}

		@Override
		public void scheduleDrawable(Drawable drawable, Runnable runnable, long when) {}

		@Override
		public void unscheduleDrawable(Drawable drawable, Runnable runnable) {}
	};

	// Load the list of actors.
	private class CastList extends AsyncTask<String, Void, String> {

		private final String API_KEY = ConfigHelper.getConfigValue(
				getApplicationContext(), "api_key");

		protected String doInBackground(String ... params) {
			String line;
			StringBuilder stringBuilder = new StringBuilder();

			String movie = (isMovie) ? "movie" : "tv";
			
			// Load the list with actors that played in the movie.
			try {
				URL url = new URL("https://api.themoviedb.org/3/" + movie + "/" + 
						movieId + "?api_key=" + API_KEY + 
						"&append_to_response=credits" + getLanguageParameter());
				URLConnection urlConnection = url.openConnection();

				try {
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(
							urlConnection.getInputStream()));

					// Create one long string of the webpage.
					while((line = bufferedReader.readLine()) != null) {
						stringBuilder.append(line).append("\n");
					}

					// Close connection and return the data from the webpage.
					bufferedReader.close();
					return stringBuilder.toString();
				} catch(IOException ioe) {
					ioe.printStackTrace();
				}
			} catch(MalformedURLException mue) {
				mue.printStackTrace();
			} catch(IOException ioe) {
				ioe.printStackTrace();
			}

			// Loading the dataset failed, return null.
			return null;
		}

		protected void onPostExecute(String response) {
			// Set all the actors in a list and send that to the adapter.
			try {
				JSONObject reader = new JSONObject(response);
				JSONObject creditData = reader.getJSONObject("credits");
				JSONArray castArray = creditData.getJSONArray("cast");
				for(int i = 0; i < castArray.length(); i++) {
					JSONObject castData = castArray.getJSONObject(i);
					castArrayList.add(castData);
				}
				castAdapter = new CastBaseAdapter(castArrayList,
						getApplicationContext());
				
				castView.setAdapter(castAdapter);
			} catch(JSONException je) {
				je.printStackTrace();
			}
		}
	}

	// Load a list with similar movies.
	private class SimilarMovieList extends AsyncTask<String, Void, String> {

		private final String API_KEY = ConfigHelper.getConfigValue(
				getApplicationContext(), "api_key");

		protected String doInBackground(String ... params) {
			String line;
			StringBuilder stringBuilder = new StringBuilder();

			String movie = (isMovie) ? "movie" : "tv";
			
			// Load the webpage with the list of similar movies.
			try {
				URL url = new URL("https://api.themoviedb.org/3/" + movie + "/" +
						movieId + "/similar?api_key=" + 
						API_KEY + getLanguageParameter());
				URLConnection urlConnection = url.openConnection();

				try {
					BufferedReader bufferedReader = new BufferedReader(
							new InputStreamReader(
							urlConnection.getInputStream()));

					// Create one long string of the webpage.
					while((line = bufferedReader.readLine()) != null) {
						stringBuilder.append(line).append("\n");
					}

					// Close connection and return the data from the webpage.
					bufferedReader.close();
					return stringBuilder.toString();
				} catch(IOException ioe) {
					ioe.printStackTrace();
				}
			} catch(MalformedURLException mue) {
				mue.printStackTrace();
			} catch(IOException ioe) {
				ioe.printStackTrace();
			}

			// Loading the dataset failed, return null.
			return null;
		}

		protected void onPostExecute(String response) {
			// Set all the similar movies in a list and send that to the adapter.
			try {
				JSONObject reader = new JSONObject(response);
				JSONArray similarMovieArray = reader.getJSONArray("results");
				for(int i = 0; i < similarMovieArray.length(); i++) {
					JSONObject movieData = similarMovieArray.getJSONObject(i);
					similarMovieArrayList.add(movieData);
				}
				similarMovieAdapter = new SimilarMovieBaseAdapter(
						similarMovieArrayList, getApplicationContext());
				
				similarMovieView.setAdapter(similarMovieAdapter);
			} catch(JSONException je) {
				je.printStackTrace();
			}
		}
	}

	// Load the movie details.
	private class MovieDetails extends AsyncTask<String, Void, String> {

		private final String API_KEY = ConfigHelper.getConfigValue(
				getApplicationContext(), "api_key");
		private boolean missingOverview;

		protected String doInBackground(String... params) {
			if(params.length > 0) {
				missingOverview = params[0].equalsIgnoreCase("true");
			}

			String line;
			StringBuilder stringBuilder = new StringBuilder();

			// Load the movie webpage (and check for updates/corrections).
			try {
				String type = (isMovie) ? "movie" : "tv";
				URL url;
				if(missingOverview) {
					url = new URL("https://api.themoviedb.org/3/" + type + 
							"/" + movieId + "?api_key=" + API_KEY);
				} else {
					url = new URL("https://api.themoviedb.org/3/" + type + 
							"/" + movieId + "?api_key=" + API_KEY 
							+ getLanguageParameter());
				}
				URLConnection urlConnection = url.openConnection();

				try {
					BufferedReader bufferedReader = new BufferedReader(
						new InputStreamReader(
						urlConnection.getInputStream()));

					// Create one long string of the webpage.
					while((line = bufferedReader.readLine()) != null) {
						stringBuilder.append(line).append("\n");
					}

					// Close connection and return the data from the webpage.
					bufferedReader.close();
					return stringBuilder.toString();
				} catch(IOException ioe) {
					ioe.printStackTrace();
				}
			} catch(MalformedURLException mue) {
				mue.printStackTrace();
			} catch(IOException ioe) {
				ioe.printStackTrace();
			}

			// Loading the dataset failed, return null.
			return null;
		}

		protected void onPostExecute(String response) {
			// Send the dataset to setMovieData to change the data where needed.
			try {
				JSONObject movieData = new JSONObject(response);
				// If the translation is missing, only change the overview.
				// Doing this with setMovieData would change everything to English.
				// To prevent that, we use this if-statement.
				if(missingOverview) {
					movieDescription.setText(movieData.getString("overview"));
				} else {
					setMovieData(movieData);
				}
			} catch(JSONException e) {
				e.printStackTrace();
			}
		}
	}
}
